#include "Player.h"
#include "StageManager.h"
#include "Cloth.h"
#include "Inventory.h"

Player::Player() {
	m_ptransform = new osg::PositionAttitudeTransform();
	m_ptransformExclam = new osg::PositionAttitudeTransform();
	m_pinventory = new Inventory();
}

Player::~Player() {
}

void Player::init() {
	// Load player model
	player = osgDB::readNodeFile("../data/mesh/player.osg");
	
	m_ptransform->addChild(player);
	m_ptransform->setPosition(osg::Vec3(10, 25, 0));
	
	player->accept(bbox);
	
	// Load Exclamation mark model
	exclamationMark = osgDB::readNodeFile("../data/mesh/exclamation_mark.osg");
	
	m_ptransformExclam->addChild(exclamationMark);
	m_ptransformExclam->setPosition(osg::Vec3(-100, -100, 2));

	// Declare instance of class to record state of keyboard
	m_pkeyState = new KeyboardState();

	// Set up the update callback
	//  pass the constructor a pointer to our input device state
	//  that we declared above.
	m_pposCallback = new PlayerPositionCallback(m_pkeyState);
	m_ptransform->setUpdateCallback(m_pposCallback);

	// The constructor for our event handler also gets a pointer to
	//   our input device state instance
	KeyboardEventHandler* playerEventHandler = new KeyboardEventHandler(m_pkeyState);

	// Add our event handler to the list
	Engine::getInstance().getViewer().addEventHandler(playerEventHandler);

	StageManager::getInstance().getRootNode()->addChild(m_ptransformExclam);
	StageManager::getInstance().getRootNode()->addChild(m_ptransform);

	m_pinventory->init();
	// he is not hidden at first
	m_bisHidded = false;
	
}

void Player::update() {
	ComputeBoundingBox b;
	player->accept(b);
	bbox = b;
	
}

void PlayerPositionCallback::operator()(osg::Node* node, osg::NodeVisitor* nv) {
	if(Engine::getInstance().getTimer()->isRunning()){
		AbstractStage * stage = StageManager::getInstance().getCurrentStage();
		if (m_pkeyState->isUp() && m_pkeyState->m_key == 'p') {
			Engine::getInstance().getTimer()->pause();
			stage->getHud()->pause();
		}
		// if the player is Hidden, he can't move
		if(!stage->getPlayer()->isHidded() && !Engine::getInstance().getTimer()->isPause()){

			osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*> (node);
			if(pat) {
				osg::Vec3d pos;
				if (m_pkeyState->m_keydown){
					if (stage->computeCollision(stage->getPlayer())) {
						pat->setPosition(m_lastPos);
						pat->setAttitude(m_lastAtt);
					}else{
						m_lastPos = pat->getPosition();
						m_lastAtt = pat->getAttitude();
					}

					pos = pat->getPosition();
					stage->computeInteraction(stage->getPlayer());

					// Update position
					if (m_pkeyState->m_key == osgGA::GUIEventAdapter::KEY_Up) {
						  pos.y() += 0.15;
					}
					else if (m_pkeyState->m_key == osgGA::GUIEventAdapter::KEY_Down) {
						if(pos.y() > 0.) 
						  pos.y() -= 0.15;
					}
					else if (m_pkeyState->m_key == osgGA::GUIEventAdapter::KEY_Left) {
						if(pos.x() > 0.) 
						  pos.x() -= 0.15;
					}
					else if (m_pkeyState->m_key == osgGA::GUIEventAdapter::KEY_Right) {
						  pos.x() += 0.15;
					}
					pat->setPosition(pos);

					// Update player orientation
					osg::Vec3d direction = pos - m_lastPos;
					direction.normalize();

					double angle= 0;
					if (direction[0]>=0) {
						angle = -acos(direction[1]);
					} else {
						angle = acos(direction[1]);
					}
					osg::Quat att = osg::Quat(angle, osg::Vec3d(0.0, 0.0, 1.0));
					// The bounding box isn't a centered cube, so rotate the player model causes collisions problems
					//pat->setAttitude(att);
					
				}
			}
			traverse(node, nv); 
		}
	}
}